﻿Imports Microsoft.Reporting.WebForms
Imports Equipment.Business
Imports Equipment.DataAccess
Imports Equipment.Report
Imports AppUser = Equipment.DataAccess.User
Imports ReportWorkOrderWrapper = Equipment.Report.WorkOrderWrapper
Imports ReportAssetWrapper = Equipment.Report.AssetWrapper

Namespace Equipment
    <Authorize()> _
    Public Class ReportController
        Inherits System.Web.Mvc.Controller

        '
        ' GET: /Report
        Function Index() As ActionResult
            Return View()
        End Function

#Region "Asset"
        Function AssetCriteria() As ActionResult
            Dim assetTypes = AssetType.RetrieveAll()
            Dim sites = SiteDepartmentManager.GetAllFor(Application.CurrentUserInfo)
            Dim locations = SiteDepartmentManager.GetAllDepartmentsFor(Application.CurrentUserInfo)
            Dim assetStatuses = AssetStatus.RetrieveAll()

            ViewData("Site") = New SelectList(sites, "ID", "Description")
            ViewData("Department") = New SelectList(locations, "ID", "Description")
            ViewData("AssetType") = New SelectList(assetTypes, "ID", "Description")
            ViewData("Status") = New SelectList(assetStatuses, "ID", "Description")

            Return View()
        End Function

        <HttpPost()> _
        Function AssetReport(ByVal collection As FormCollection) As ActionResult
            Dim assetTypeID = 0
            Dim siteID = 0
            Dim locationID = 0
            Dim groupID = 0
            Dim assetStatusID = 0

            Integer.TryParse(collection("Site"), siteID)
            Integer.TryParse(collection("Group"), groupID)
            Integer.TryParse(collection("Department"), locationID)
            Integer.TryParse(collection("AssetType"), assetTypeID)
            Integer.TryParse(collection("Status"), assetStatusID)

            Dim assets As IEnumerable(Of Asset) = AssetManager.GetFiltered(siteID, locationID, assetTypeID, groupID, assetStatusID)

            ViewData("Assets") = ReportAssetWrapper.ConvertToWrapperList(assets)

            ViewData("ReportType") = ReportType.Asset
            ViewData("SiteID") = siteID
            ViewData("DepartmentID") = locationID
            ViewData("GroupID") = groupID
            ViewData("AssetTypeID") = assetTypeID
            ViewData("StatusID") = assetStatusID
            Return View()
        End Function

#End Region


#Region "Basic Requirement Detail"
        Function BasicRequirementDetailCriteria() As ActionResult
            Dim requirements = Requirement.RetrieveAll()

            ViewData("Requirement") = New SelectList(requirements, "ID", "Name")

            Return View()
        End Function

        <HttpPost()> _
        Function BasicRequirementDetailReport(ByVal collection As FormCollection) As ActionResult
            Dim id = 0

            Integer.TryParse(collection("Requirement"), id)

            Dim req = Requirement.GetByPrimaryKey(id)
            ViewData("Requirement") = RequirementDetailWrapper.GetFrom(req)
            ViewData("Measures") = MeasureWrapper.ConvertToWrapperList(req.Measures)

            ViewData("ReportType") = ReportType.BasicRequirementDetail
            ViewData("RequirementID") = id

            Return View()
        End Function

#End Region


#Region "Basic Requirement"
        Function BasicRequirementCriteria() As ActionResult
            Dim assetTypes = AssetType.RetrieveAll()

            ViewData("AssetTypeID") = New SelectList(assetTypes, "ID", "Description")

            Return View()
        End Function

        <HttpPost()> _
        Function BasicRequirementReport(ByVal collection As FormCollection) As ActionResult
            Dim assetTypeID = 0
            Dim frequency = collection("Frequency")
            Integer.TryParse(collection("AssetTypeID"), assetTypeID)

            Dim requirements As IEnumerable(Of Requirement)

            If String.IsNullOrEmpty(frequency) Then
                requirements = Requirement.RetrieveAll(assetTypeID)
            Else
                Dim frequencyList = RequirementFrequencyHelper.GetListByFrequencyString(frequency)
                requirements = Requirement.RetrieveAll(assetTypeID, frequencyList)
            End If

            ViewData("Requirements") = RequirementWrapper.ConvertToWrapperList(requirements)


            ViewData("ReportType") = ReportType.BasicRequirement
            ViewData("AssetTypeID") = assetTypeID
            ViewData("Frequency") = frequency

            Return View()
        End Function

#End Region

#Region "Group"
        Function GroupCriteria() As ActionResult
            Dim sites = SiteDepartmentManager.GetAllFor(Application.CurrentUserInfo)
            Dim locations = SiteDepartmentManager.GetAllDepartmentsFor(Application.CurrentUserInfo)

            ViewData("Site") = New SelectList(sites, "ID", "Description")
            ViewData("Department") = New SelectList(locations, "ID", "Description")

            Return View()
        End Function

        <HttpPost()> _
        Function GroupReport(ByVal collection As FormCollection) As ActionResult
            Dim siteID As Integer = 0
            Dim locationID As Integer = 0

            Integer.TryParse(collection("Site"), siteID)
            Integer.TryParse(collection("Department"), locationID)

            ViewData("Groups") = GroupWrapper.ConvertToWrapperList(Group.RetrieveAll(siteID, locationID))

            ViewData("ReportType") = ReportType.Group
            ViewData("SiteID") = siteID
            ViewData("DepartmentID") = locationID

            Return View()
        End Function

#End Region

#Region "Holiday"
        Function HolidayCriteria() As ActionResult
            Dim dateFrom As DateTime = DateTime.UtcNow.Date.AddDays(-DateTime.UtcNow.Date.Day + 1)
            Dim dateTo As DateTime = DateTime.UtcNow.Date.AddDays(1).AddSeconds(-1)
            
            ViewData("DateFrom") = dateFrom.ToString("dd-MMM-yyyy")
            ViewData("DateTo") = dateTo.ToString("dd-MMM-yyyy")
            Return View()
        End Function

        <HttpPost()> _
        Function HolidayReport(ByVal collection As FormCollection) As ActionResult
            Dim period = ReportPeriod.ReadFromFormCollection(collection)

            ViewData("DateFrom") = period.StartDate.ToString("dd-MMM-yyyy")
            ViewData("DateTo") = period.EndDate.ToString("dd-MMM-yyyy")

            ViewData("ReportType") = ReportType.Holiday
            ViewData("Holidays") = Holiday.RetrieveAll(period.StartDate, period.EndDate)

            Return View()
        End Function

#End Region

#Region "User"
        Function UserCriteria() As ActionResult
            Dim sites = SiteDepartmentManager.GetAllFor(Application.CurrentUserInfo)
            Dim locations = SiteDepartmentManager.GetAllDepartmentsFor(Application.CurrentUserInfo)
            Dim roles = RoleManager.GetAllFor(Application.CurrentUserInfo)
            Dim groups = GroupManager.GetAllFor(Application.CurrentUserInfo)

            ViewData("Site") = New SelectList(sites, "ID", "Description")
            ViewData("Department") = New SelectList(locations, "ID", "Description")
            ViewData("Group") = New SelectList(groups, "ID", "Description")
            ViewData("Role") = New SelectList(roles, "ID", "Description")

            Return View()
        End Function

        <HttpPost()> _
        Function UserReport(ByVal collection As FormCollection) As ActionResult
            Dim siteID As Integer = 0
            Dim groupID As Integer = 0
            Dim roleID As Integer = 0

            Integer.TryParse(collection("Site"), siteID)
            Integer.TryParse(collection("Group"), groupID)
            Integer.TryParse(collection("Role"), roleID)

            ViewData("Users") = UserWrapper.ConvertToWrapperList(AppUser.RetrieveAll(siteID, roleID, groupID, 0))

            ViewData("ReportType") = ReportType.User
            ViewData("SiteID") = siteID
            ViewData("GroupID") = groupID
            ViewData("RoleID") = roleID
            Return View()
        End Function

#End Region

#Region "Employee Work"
        Function EmployeeWorkCriteria() As ActionResult
            Dim dateFrom As DateTime = DateTime.UtcNow.Date.AddDays(-DateTime.UtcNow.Date.Day + 1)
            Dim dateTo As DateTime = DateTime.UtcNow.Date.AddDays(1).AddSeconds(-1)
            Dim users = UserManager.GetAllFor(Application.CurrentUserInfo)

            ViewData("User") = New SelectList(users, "ID", "FullName")
            ViewData("DateFrom") = dateFrom.ToString("dd-MMM-yyyy")
            ViewData("DateTo") = dateTo.ToString("dd-MMM-yyyy")

            Return View()
        End Function

        <HttpPost()> _
        Function EmployeeWorkReport(ByVal collection As FormCollection) As ActionResult

            Dim period = ReportPeriod.ReadFromFormCollection(collection)
            Dim userID = Integer.Parse(collection("User"))
            Dim empoyee As AppUser = AppUser.GetByPrimaryKey(userID)

            ViewData("DateFrom") = period.StartDate.ToString("dd-MMM-yyyy")
            ViewData("DateTo") = period.EndDate.ToString("dd-MMM-yyyy")
            ViewData("UserID") = userID
            ViewData("EmployeeFullName") = empoyee.FullName

            ViewData("ReportType") = ReportType.EmployeeWork
            ViewData("Holidays") = Holiday.RetrieveAll(period.StartDate, period.EndDate)

            ViewData("WorkOrders") = EmployeeWorkWrapper.ConvertToWrapperList(WorkOrder.RetrieveAllPerformedBy(userID, period.StartDate, period.EndDate))

            Return View()
        End Function

#End Region

#Region "Work Orders"
        Function WorkOrderCriteria() As ActionResult
            Dim assetTypes = AssetType.RetrieveAll()
            Dim locations = SiteDepartmentManager.GetAllDepartmentsFor(Application.CurrentUserInfo)
            Dim groups = GroupManager.GetAllFor(Application.CurrentUserInfo)
            Dim statuses = WorkOrderStatus.RetrieveAll()

            ViewData("Department") = New SelectList(locations, "ID", "Description")
            ViewData("Group") = New SelectList(groups, "ID", "Description")
            ViewData("AssetType") = New SelectList(assetTypes, "ID", "Description")
            ViewData("Status") = New SelectList(statuses, "ID", "Description")
            ViewData("WorkOrderDate") = DateTime.UtcNow.ToString("dd-MMM-yyyy")

            Return View()
        End Function

        <HttpPost()> _
        Function WorkOrderReport(ByVal collection As FormCollection) As ActionResult
            Dim assetTypeID = 0
            Dim siteID = 0
            Dim locationID = 0
            Dim groupID = 0
            Dim woDate As DateTime
            Dim woEndDate As DateTime
            Dim formStatus As String = collection("Status")
            Dim formAcceptance As String = collection("ddlAcceptance")

            Integer.TryParse(collection("Group"), groupID)
            Integer.TryParse(collection("Department"), locationID)
            Integer.TryParse(collection("AssetType"), assetTypeID)
            DateTime.TryParse(collection("WorkOrderDate"), woDate)

            Dim workOrders As IEnumerable(Of WorkOrder)

            If Not DateTime.TryParse(collection("WorkOrderDate"), woDate) Then
                woDate = DateTime.UtcNow.Date.AddYears(-5)
                woEndDate = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1)
            Else
                woEndDate = woDate.AddDays(1).AddMilliseconds(-1)
            End If


            If Not String.IsNullOrEmpty(formStatus) Then
                Dim status As WorkOrderStatusType = [Enum].Parse(GetType(WorkOrderStatusType), formStatus)
                workOrders = WorkOrder.RetrieveAllByStatus(assetTypeID, locationID, groupID, woDate, woEndDate, status)
                ViewData("Status") = formStatus
            Else
                workOrders = WorkOrder.RetrieveAll(assetTypeID, locationID, groupID, woDate, woEndDate)
            End If

            If Not String.IsNullOrEmpty(formAcceptance) Then
                If formAcceptance = "Accepted" Then
                    workOrders = workOrders.Where(Function(wo) (wo.ReviewType = RequirementReviewType.Required Or wo.ReviewType = RequirementReviewType.RequiredOnlyForException) AndAlso wo.ApprovedDate IsNot Nothing)
                Else
                    workOrders = workOrders.Where(Function(wo) (wo.ReviewType = RequirementReviewType.Required Or wo.ReviewType = RequirementReviewType.RequiredOnlyForException) AndAlso wo.ApprovedDate Is Nothing)
                End If
            End If

            ViewData("WorkOrders") = ReportWorkOrderWrapper.ConvertToWrapperList(workOrders)

            ViewData("ReportType") = ReportType.WorkOrder
            ViewData("DepartmentID") = locationID
            ViewData("GroupID") = groupID
            ViewData("AssetTypeID") = assetTypeID
            ViewData("DateFrom") = woDate.ToString()
            ViewData("DateTo") = woEndDate.ToString()


            Return View()
        End Function

#End Region

#Region "Work Order Detail"
        Function WorkOrderDetailCriteria() As ActionResult
            Dim workOrders = WorkOrderManager.GetAllFor(Application.CurrentUserInfo)

            ViewData("WorkOrder") = New SelectList(workOrders, "ID", "ID")

            Return View()
        End Function

        <HttpPost()> _
        Function WorkOrderDetailReport(ByVal collection As FormCollection) As ActionResult
            Dim workOrderID = 0

            Integer.TryParse(collection("WorkOrder"), workOrderID)
            Dim wo = WorkOrder.GetByPrimaryKey(workOrderID)

            ViewData("WorkOrder") = wo
            ViewData("WorkOrderID") = workOrderID
            ViewData("History") = WorkOrderHistoryWrapper.GetHistoryListFrom(wo)

            ViewData("ReportType") = ReportType.WorkOrderDetail

            Return View()
        End Function

#End Region

        Function GetDataSourceByReportType(ByVal type As ReportType, ByVal collection As FormCollection) As Object
            If type = ReportType.Holiday Then
                Dim period = ReportPeriod.ReadFromFormCollection(collection)
                Return Holiday.RetrieveAll(period.StartDate, period.EndDate)
            ElseIf type = ReportType.User Then
                Dim siteID As Integer = Integer.Parse(collection("SiteID"))
                Dim groupID As Integer = Integer.Parse(collection("GroupID"))
                Dim roleID As Integer = Integer.Parse(collection("RoleID"))
                Return UserWrapper.ConvertToWrapperList(AppUser.RetrieveAll(siteID, roleID, groupID, 0))
            ElseIf type = ReportType.Group Then
                Dim siteID As Integer = Integer.Parse(collection("SiteID"))
                Dim locationID As Integer = Integer.Parse(collection("DepartmentID"))
                Return GroupWrapper.ConvertToWrapperList(Group.RetrieveAll(siteID, locationID))
            ElseIf type = ReportType.WorkOrder Then
                Dim assetTypeID = Integer.Parse(collection("AssetTypeID"))
                Dim locationID = Integer.Parse(collection("DepartmentID"))
                Dim groupID = Integer.Parse(collection("GroupID"))
                Dim period = ReportPeriod.ReadFromFormCollection(collection)
                Dim formStatus As String = collection("Status")
                Dim formAcceptance As String = collection("ddlAcceptance")
                Dim workOrders As IEnumerable(Of WorkOrder)

                If Not String.IsNullOrEmpty(formStatus) Then
                    Dim status As WorkOrderStatusType = [Enum].Parse(GetType(WorkOrderStatusType), formStatus)
                    workOrders = WorkOrder.RetrieveAllByStatus(assetTypeID, locationID, groupID, period.StartDate, period.EndDate, status)
                Else
                    workOrders = WorkOrder.RetrieveAll(assetTypeID, locationID, groupID, period.StartDate, period.EndDate)
                End If

                If Not String.IsNullOrEmpty(formAcceptance) Then
                    If formAcceptance = "Accepted" Then
                        workOrders = workOrders.Where(Function(wo) (wo.ReviewType = RequirementReviewType.Required Or wo.ReviewType = RequirementReviewType.RequiredOnlyForException) AndAlso wo.ApprovedDate IsNot Nothing)
                    Else
                        workOrders = workOrders.Where(Function(wo) (wo.ReviewType = RequirementReviewType.Required Or wo.ReviewType = RequirementReviewType.RequiredOnlyForException) AndAlso wo.ApprovedDate Is Nothing)
                    End If
                End If

                Return ReportWorkOrderWrapper.ConvertToWrapperList(workOrders)
            ElseIf type = ReportType.Asset Then
                Dim siteID = Integer.Parse(collection("SiteID"))
                Dim assetTypeID = Integer.Parse(collection("AssetTypeID"))
                Dim locationID = Integer.Parse(collection("DepartmentID"))
                Dim groupID = Integer.Parse(collection("GroupID"))
                Dim AssetStatusID = Integer.Parse(collection("StatusID"))
                Dim assets As IEnumerable(Of Asset) = AssetManager.GetFiltered(siteID, locationID, assetTypeID, groupID, AssetStatusID)
                Return ReportAssetWrapper.ConvertToWrapperList(assets)
            ElseIf type = ReportType.EmployeeWork Then
                Dim period = ReportPeriod.ReadFromFormCollection(collection)
                Dim userID = Integer.Parse(collection("UserID"))
                Return EmployeeWorkWrapper.ConvertToWrapperList(WorkOrder.RetrieveAllPerformedBy(userID, period.StartDate, period.EndDate))
            ElseIf type = ReportType.BasicRequirement Then
                Dim frequency = collection("ddlFrequency")
                Dim assetTypeID As Integer = Integer.Parse(collection("AssetTypeID"))
                If String.IsNullOrEmpty(frequency) Then
                    Return RequirementWrapper.ConvertToWrapperList(Requirement.RetrieveAll(assetTypeID))
                Else
                    Dim frequencyList = RequirementFrequencyHelper.GetListByFrequencyString(frequency)
                    Return RequirementWrapper.ConvertToWrapperList(Requirement.RetrieveAll(assetTypeID, frequencyList))
                End If
            End If

            Return Nothing
        End Function

        <HttpPost()> _
        Function Export(ByVal collection As FormCollection) As ActionResult
            Dim formReportType As ReportType = [Enum].Parse(GetType(ReportType), collection("hfReportType"))
            Dim formExportFormat As String = collection("hfExportFormat")
            Dim dataSource = GetDataSourceByReportType(formReportType, collection)

            If formReportType = ReportType.WorkOrderDetail Then
                Dim id As Integer = Integer.Parse(collection("WorkOrderID"))
                Dim wo = WorkOrder.GetByPrimaryKey(id)
                dataSource = WorkOrderHistoryWrapper.GetHistoryListFrom(wo)
                Return GenerateReport(formReportType, formExportFormat, dataSource, "WorkOrder_ID", id.ToString(), _
                                                                                    "WorkOrder_Description", wo.Description, _
                                                                                    "WorkOrder_Status", WorkOrderStatus.GetDescriptionByType(wo.Status), _
                                                                                    "WorkOrder_DateDue", wo.DateDue.ToString("dd-MMM-yyyy hh:mm"), _
                                                                                    "RequirementName", wo.Requirement.Name, _
                                                                                    "RequirementType", RequirementTypeLookup.GetDescriptionByType(wo.RequirementType), _
                                                                                    "AssetType", wo.Asset.AssetType.Description, _
                                                                                    "Frequency", wo.Requirement.Frequency.ToString(), _
                                                                                    "AssetId", wo.AssetID, _
                                                                                    "AssetName", wo.Asset.AssetName, _
                                                                                    "Department", wo.Asset.SiteDepartment.Description, _
                                                                                    "ModelNo", wo.Asset.ModelNo, _
                                                                                    "SerialNo", wo.Asset.ModelNo)
            ElseIf formReportType = ReportType.BasicRequirementDetail Then
                Dim id As Integer = Integer.Parse(collection("RequirementID"))
                Dim req = Requirement.GetByPrimaryKey(id)
                Dim reqWrapper = RequirementDetailWrapper.GetFrom(req)
                dataSource = MeasureWrapper.ConvertToWrapperList(req.Measures)
                Return GenerateReport(formReportType, formExportFormat, dataSource, "ID", id.ToString(), _
                                                                                    "RequirementName", req.Name, _
                                                                                    "RequirementType", reqWrapper.RequirementTypeDescription, _
                                                                                    "AssetType", reqWrapper.AssetTypeDescription, _
                                                                                    "Frequency", reqWrapper.FrequencyInfo, _
                                                                                    "Created", reqWrapper.FormatedCreatedDate, _
                                                                                    "CreatedBy", reqWrapper.CreatedByUserFullName, _
                                                                                    "TimeUsage", reqWrapper.TimeUsage)

            ElseIf formReportType = ReportType.WorkOrderDetail Then
                Dim userID As Integer = Integer.Parse(collection("userID"))
                Dim employee As AppUser = AppUser.GetByPrimaryKey(userID)
                Return GenerateReport(formReportType, formExportFormat, dataSource, "Employee_FullName", employee.FullName)
            Else
                Return GenerateReport(formReportType, formExportFormat, dataSource)
            End If
        End Function


        Function GenerateReport(ByVal reportType As ReportType, ByVal exportFormat As String, ByVal ds As Object, ByVal ParamArray params As String()) As ActionResult

            Dim localReport As New LocalReport()
            localReport.ReportPath = Server.MapPath(String.Format("~/Reports/{0}Report.rdlc", reportType.ToString()))

            If ds IsNot Nothing Then
                Dim reportDataSource As New ReportDataSource(String.Format("{0}DataSet", reportType.ToString()), ds)
                localReport.DataSources.Add(reportDataSource)
            End If

            Dim reportParams As New List(Of ReportParameter)
            For i As Integer = 0 To params.Length - 1 Step 2
                Dim paramName As String = params(i)
                Dim paramValue As String = params(i + 1)
                Dim param As New ReportParameter(paramName, paramValue)
                reportParams.Add(param)
            Next

            If params.Length > 0 Then
                localReport.SetParameters(reportParams)
            End If

            Dim mimeType As String
            Dim encoding As String
            Dim fileNameExtension As String

            'The DeviceInfo settings should be changed based on the reportType
            'http://msdn2.microsoft.com/en-us/library/ms155397.aspx
            Dim deviceInfo As String = "<DeviceInfo>" & "  <OutputFormat>" & exportFormat & "</OutputFormat>" & "  <PageWidth>8.5in</PageWidth>" & "  <PageHeight>11in</PageHeight>" & "  <MarginTop>0.5in</MarginTop>" & "  <MarginLeft>1in</MarginLeft>" & "  <MarginRight>1in</MarginRight>" & "  <MarginBottom>0.5in</MarginBottom>" & "</DeviceInfo>"

            Dim warnings As Warning()
            Dim streams As String()
            Dim renderedBytes As Byte()

            'Render the report
            renderedBytes = localReport.Render(exportFormat, deviceInfo, mimeType, encoding, fileNameExtension, streams, warnings)
            'Response.AddHeader("content-disposition", "attachment; filename=NorthWindCustomers." + fileNameExtension);
            Return File(renderedBytes, mimeType)

        End Function

#Region "Inner"
        Public Class ReportPeriod
            Public StartDate As DateTime
            Public EndDate As DateTime

            Public Shared Function ReadFromFormCollection(ByVal collection As FormCollection) As ReportPeriod
                Dim period As New ReportPeriod

                Dim strDateFrom As String = collection("txtDateFrom")
                Dim strDateTo As String = collection("txtDateTo")
                period.StartDate = DateTime.UtcNow.Date.AddYears(-5)
                period.EndDate = DateTime.UtcNow.Date

                If Not String.IsNullOrEmpty(strDateFrom) Then
                    DateTime.TryParse(strDateFrom, period.StartDate)
                End If

                If Not String.IsNullOrEmpty(strDateTo) Then
                    DateTime.TryParse(strDateTo, period.EndDate)
                End If

                period.EndDate = period.EndDate.AddDays(1).AddSeconds(-1)

                Return period
            End Function

        End Class
#End Region


    End Class
End Namespace